﻿using System;
using System.Linq;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Text;
using System.Windows.Forms;
using Superbaby.PrettyUI.Forms;

namespace Superbaby.PrettyUI.Forms
{
    public partial class BubbleTextPanel : Control
    {
        private string _text;
        private bool _autoHeight;
        private int _width = 0;

        public BubbleTextPanel()
        {
            this.CornerWidth = 10;
            this.FillColor = Color.LightYellow;
            this.BorderColor = Color.Gray;
            this.BackColor = SystemColors.Window;
            this.TabStop = false;

            InitializeComponent();
        }

        protected override void OnPaint(PaintEventArgs pe)
        {
            if (this.ClientRectangle.Width > 0 && this.ClientRectangle.Height > 0)
            {
                //double buffer to reduce blink
                using (Bitmap bitmap = new Bitmap(this.ClientRectangle.Width, this.ClientRectangle.Height))
                {
                    using (Graphics buffer = Graphics.FromImage(bitmap))
                    {
                        buffer.Clear(this.BackColor);

                        int borderColor = HelperMethods.ColorToWin32(this.BorderColor);
                        int fillColor = HelperMethods.ColorToWin32(this.FillColor);

                        //call native method to draw a filled round rectangle
                        IntPtr hdc = buffer.GetHdc();
                        try
                        {
                            IntPtr hPen = NativeMethods.CreatePen(NativeMethods.PS_SOLID, 1, borderColor);
                            IntPtr hOldPen = NativeMethods.SelectObject(hdc, hPen);

                            IntPtr hBrush = NativeMethods.CreateSolidBrush(fillColor);
                            IntPtr hOldBrush = NativeMethods.SelectObject(hdc, hBrush);

                            NativeMethods.RoundRect(hdc, 0, 0, this.Width, this.Height, this.CornerWidth, this.CornerWidth);

                            NativeMethods.SelectObject(hdc, hOldBrush);
                            NativeMethods.SelectObject(hdc, hOldPen);

                            NativeMethods.DeleteObject(hBrush);
                            NativeMethods.DeleteObject(hPen);
                        }
                        finally
                        {
                            buffer.ReleaseHdc(hdc);
                        }

                        //prepare calulate rectangle, helper method will comput the actual text size
                        Rectangle calRect = new Rectangle(this.CornerWidth / 2, this.CornerWidth / 2,
                            this.ClientRectangle.Width - this.CornerWidth, this.ClientRectangle.Height - this.CornerWidth);

                        int textHeight;
                        textHeight = HelperMethods.MeasureStringEx(buffer, _text, this.Font, calRect).Height;

                        RectangleF textRect = new RectangleF(this.CornerWidth / 2, this.CornerWidth / 2,
                            this.ClientRectangle.Width - this.CornerWidth, textHeight);

                        using (SolidBrush brush = new SolidBrush(this.ForeColor))
                        {
                            buffer.DrawString(_text, this.Font, brush, textRect);
                        }

                        pe.Graphics.DrawImage(bitmap, 0, 0);
                    }
                }
            }
        }

        public Color BorderColor
        {
            get;
            set;
        }

        public Color FillColor
        {
            get;
            set;
        }

        [DefaultValue(10)]
        public int CornerWidth
        {
            get;
            set;
        }

        public override string Text
        {
            get
            {
                return _text;
            }
            set
            {
                _text = value;

                if (this._autoHeight)
                {
                    if (this.ClientRectangle.Width > 0 && this.ClientRectangle.Height > 0)
                    {
                        int textHeight;

                        using (Graphics g = this.CreateGraphics())
                        {
                            //prepare calulate rectangle, helper method will comput the actual text size
                            Rectangle calRect = new Rectangle(this.CornerWidth / 2, this.CornerWidth / 2,
                                this.ClientRectangle.Width - this.CornerWidth, this.ClientRectangle.Height - this.CornerWidth);

                            textHeight = HelperMethods.MeasureStringEx(g, _text, this.Font, calRect).Height;
                        }

                        this.Height = textHeight + this.CornerWidth;
                    }
                }

                Invalidate();
            }
        }

        public bool AutoHeight
        {
            get
            {
                return _autoHeight;
            }
            set
            {
                _autoHeight = value;

                Invalidate();
            }
        }

        protected override void OnResize(EventArgs e)
        {
            base.OnResize(e);

            if (this.Width != _width)
            {
                if (this._autoHeight)
                {
                    if (this.ClientRectangle.Width > 0 && this.ClientRectangle.Height > 0)
                    {
                        int textHeight;

                        using (Graphics g = this.CreateGraphics())
                        {
                            //prepare calulate rectangle, helper method will comput the actual text size
                            Rectangle calRect = new Rectangle(this.CornerWidth / 2, this.CornerWidth / 2,
                                this.ClientRectangle.Width - this.CornerWidth, this.ClientRectangle.Height - this.CornerWidth);

                            textHeight = HelperMethods.MeasureStringEx(g, _text, this.Font, calRect).Height;
                        }

                        this.Height = textHeight + this.CornerWidth;
                    }
                }

                _width = this.Width;
            }

            //control won't re-paint on device after a resize action
            //we need to set it manually
            Invalidate();
        }

        protected override void OnPaintBackground(PaintEventArgs e)
        {
            //disable re-paint background to avoid blinking

            //base.OnPaintBackground(e);
        }
    }
}
